#pragma once


#include <string>
#include <cstdio>
#include <vector>
#include <thread>
#include <algorithm>
#include <cstring>
#include <memory>
#include<fstream>
#include<iostream>
#include "util.h"
using namespace std;


struct Product{
  string product_id, route_id;
  int section_num;
  Product(string &s) {
    vector<string> tmp = split(s,',');
    product_id = std::move(tmp[0]);
    section_num = std::stoi(std::move(tmp[1]));
    route_id = std::move(tmp[2]);
  }
  bool operator <(const Product& rhs) const {
    return route_id!=rhs.route_id?route_id<rhs.route_id:section_num<rhs.section_num;
  }
  friend ostream& operator<<(ostream &out, const Product & p) {
    out<<"product_id:"<<p.product_id<<",";
    out<<"route_id:"<<p.route_id<<",";
    out<<"section_num:"<<p.section_num;
    return out;
  }
};

struct Equipment{
  string  equip_name, equip_type, unit;
  Equipment(string &s) {
    vector<string> tmp = split(s,',');
    equip_name = std::move(tmp[0]);
    equip_type = std::move(tmp[1]);
    unit = std::move(tmp[2]);
  }
  friend ostream& operator<<(ostream &out, const Equipment & equip) {
    out<<"equip_name:"<<equip.equip_name<<",";
    out<<"equip_type:"<<equip.equip_type<<",";
    out<<"unit:"<<equip.unit;
    return out;
  }
};

struct Route{
  string route_id;
  vector<string> route_nums, route_names, equip_types,units;
  vector<int> cost_time_low, cost_time_high, ready_times;
  Route(string &route_id_):route_id(route_id_) {}

  void add_item(std::vector<string> &vec) {
    route_nums.push_back(vec[1]);
    route_names.push_back(vec[2]);
    equip_types.push_back(vec[3]);
    pair<int,int> cost = get_min(vec[4]);
    assert(cost.first<10000000 && cost.second<10000000);
    cost_time_low.push_back(cost.first);
    cost_time_high.push_back(cost.second);
    units.push_back(vec[5]);
    ready_times.push_back(get_min(vec.size()>6?vec[6]:"").first);
  }
  friend ostream& operator<<(ostream &out, const Route & route) {
    out<<"route_id:"<<route.route_id<<endl;
    out<<"len:"<<route.route_nums.size()<<endl;
    for(int i=0,r=route.route_nums.size();i<r;i++) {
      out<<"\t["<<i<<"] ";
      out<<"route_num:"<<route.route_nums[i]<<",";
      out<<"route_name:"<<route.route_names[i]<<",";
      out<<"equip_type:"<<route.equip_types[i]<<",";
      out<<"unit:"<<route.units[i]<<",";
      out<<"cost_time_low:"<<route.cost_time_low[i]<<",";
      out<<"cost_time_high:"<<route.cost_time_high[i]<<",";
      out<<"ready_time:"<<route.ready_times[i]<<",";
      out<<"\n";
    }
    return out;
  }
};

struct Data {
  vector<Product> products;
  vector<Route> routes;
  vector<Equipment> equips;
  Data(string prod_path="data/产品信息.csv", string equip_path="./data/设备信息.csv", string route_path="./data/工艺路线.csv") {
    ifstream fin;
    fin.open(prod_path, ios::in);
    // freopen(prod_path.c_str(),"r",stdin);
    // getline();
    string tmp;
    fin>>tmp;
    while (fin>>tmp) {
      products.emplace_back(tmp);
    }
    sort(products.begin(),products.end());
    fin.close();
    fin.open(equip_path, ios::in);
    fin>>tmp;
    while (fin>>tmp) {
      equips.emplace_back(tmp);
    }
    fin.close();
    fin.open(route_path, ios::in);
    fin>>tmp;
    while (fin>>tmp) {
      auto vec = split(tmp,',');
      if (routes.empty() or vec[0]!=routes.rbegin()->route_id) routes.emplace_back(vec[0]);
      routes.rbegin()->add_item(vec);
    }
  }
};